/*
* Poppy Game Engine - https://pgetemplate.googlecode.com/svn/
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* Copyright (c) 2008 Poppy
*/

#include "stdafx.h"
#include "CRandom.h"

namespace PGEMath
{

	CRandom::CRandom()
	{
		m_uRseed = 1;
		m_iMti = CMATH_N + 1;
	}

	unsigned int CRandom::Random( unsigned int n )
	{
		unsigned long y;
		static unsigned long mag01[2] = { 0x0, CMATH_MATRIX_A };

		if( n == 0 )
			return 0;

		if(m_iMti >= CMATH_N)
		{
			int kk;
			
			if( m_iMti == CMATH_N + 1 )
				SetRandomSeed(4357);

			for( kk = 0; kk < CMATH_N - CMATH_M; kk ++ )
			{
				y = ( m_aMt[kk] & CMATH_UPPER_MASK ) | ( m_aMt[kk + 1] & CMATH_LOWER_MASK );
				m_aMt[kk] = m_aMt[kk + CMATH_M] ^ (y >> 1) ^ mag01[y & 0x1];
			}
			for( ; kk < CMATH_N - 1; kk ++ )
			{
				y = ( m_aMt[kk] & CMATH_UPPER_MASK ) | ( m_aMt[kk + 1] & CMATH_LOWER_MASK );
				m_aMt[kk] = m_aMt[kk + (CMATH_M - CMATH_N)] ^ (y >> 1) ^ mag01[y & 0x1];
			}
			y = ( m_aMt[CMATH_N - 1] & CMATH_UPPER_MASK ) | ( m_aMt[0] & CMATH_LOWER_MASK );
			m_aMt[CMATH_N - 1] = m_aMt[CMATH_M - 1] ^ (y >> 1) ^ mag01[y & 0x1];

			m_iMti = 0;
		}

		y = m_aMt[m_iMti++];
		y ^= CMATH_TEMPERING_SHIFT_U(y);
		y ^= CMATH_TEMPERING_SHIFT_S(y) & CMATH_TEMPERING_MASK_B;
		y ^= CMATH_TEMPERING_SHIFT_T(y) & CMATH_TEMPERING_MASK_C;
		y ^= CMATH_TEMPERING_SHIFT_L(y);

		return (y%n);

	}

	void CRandom::SetRandomSeed( unsigned int n )
	{
		m_aMt[0] = n & 0xffffffff;
		for( m_iMti = 1; m_iMti < CMATH_N; m_iMti ++ )
			m_aMt[m_iMti] = (69069 * m_aMt[m_iMti-1]) & 0xffffffff;
		m_uRseed = n;
	}

	unsigned int CRandom::GetRandomSeed()
	{
		return m_uRseed;
	}

}
